import {Scope} from 'lib/scopeFactory';
import ApiFactory from 'lib/ApiFactory'
import moment from 'moment'
import _ from 'underscore'
import numeral from 'numeral'
import $ from 'jquery'
import React from 'react'

let defaultFetcher = ApiFactory({
  url: (params) => {
    return BlueWare.urlPrefix + '/app/' + params.appId + '/' + params.segment + '/' + params.action + '.json';
  },
  optionParams: ['appId','segment','action','dateName','dateNameCn'],
  params: {
    appId: {
      defaultValue: BlueWare.appId
    },
    segment: {
      defaultValue: 'anr'
    },
    action: {
      defaultValue: 'anrdata'
    },
    appVersionId:{
      defaultValue:BlueWare.appVersionId
    }
  }
});

export default class RootScope extends Scope {
  constructor(props) {
    super(props);

    this.getTableDate = this.getTableDate.bind(this);
    this.closeOtherDateMenu = this.closeOtherDateMenu.bind(this);

    this.current = moment().valueOf();

    this.$state = {
      anrRate: '--',
      anrCount: '--',
      anrUserCount: '--',

      current: this.current,

      // chart data source
      chart: {
        loading: true
      },
      chartSettings: {
        xAxis: {
          max: moment().startOf('day').add(1, 'days').subtract(1, 'hours').valueOf(),
          min: moment().startOf('day').valueOf()
        },
        tooltip: {
          useHTML: true
        }
      },

      // table data source
      list: {
        loading: true,
        data: []
      },

      // chart cache
      chartDataSource: {},
      chartDateCheckStatus: {
        'today': true,
        'yesterday': false
      },

      // chart date list
      chartDateListOpened: false,
      chartDateListSelectedValue: null,
      chartDateList: [
        {label: '清除选择', value: null},
        {label: '2 天前', value: 2},
        {label: '3 天前', value: 3},
        {label: '4 天前', value: 4},
        {label: '5 天前', value: 5},
        {label: '6 天前', value: 6},
        {label: '7 天前', value: 7},
        {label: '15 天前', value: 15},
        // {label: '30 天前', value: 30}
      ],

      // table date drap down list
      tableDateListSelectedValue: 0,
      tableDateList: [
        {
          tag: {
            endTime: this.current
          },
          value: 0,
          label: '今天'
        }
      ],

      //0 未解决 1解决
      stateCodeSelectedValue: null,

      // input search
      searchValue: null,

      // control by button: 显示隐藏的项
      showHiddenTable: false,

      listLimit: 10,
      listOffset: 0
    };

    this.$state.gridColumns = [
      {
        title:'问题描述',
        key:'name',
        containerStyle:{
          width:'48%'
        },
        sortable:true,
        render:function(cellValue,rowData){
          let spanTime = rowData.lastTime - rowData.firstTime;
          let splitIndex = cellValue.indexOf('(');

          return (
            <a className="link-in-list" href={'#/' + rowData.anrTypeId + '/' + this.props.endTime}>
              {
                splitIndex === -1
                  ? cellValue
                  : (
                    <div>
                      {cellValue.substr(0, splitIndex)}
                      <br/>
                      {cellValue.substr(splitIndex)}
                    </div>
                  )
              }
            </a>
          )
        }
      },
      {
        title:'APP 版本',
        key:'appVersion',
        sortable:true,
        containerStyle:{
          minWidth:'75px'
        },
        className: 'text-align-left'
      },
      {
        title:'发生次数',
        key:'count',
        sortable:true,
        containerStyle:{
          minWidth:'85px'
        },
        className: 'text-align-left'
      },
      {
        title:'影响用户数',
        key:'affected',
        sortable:true,
        containerStyle:{
          minWidth:'90px'
        },
        className: 'text-align-left'
      },
      {
        title:'首次发生时间',
        key:'firstTime',
        formatter: (item) => {
          return moment(item).format('YYYY/MM/DD HH:mm:ss')
        },
        sortable:true,
        containerStyle:{
          minWidth:'85px'
        },
        className: 'text-align-left'
      },
      {
        title:'最后发生时间',
        key:'lastTime',
        formatter: (item) => {
          return moment(item).format('YYYY/MM/DD HH:mm:ss')
        },
        sortable:true,
        containerStyle:{
          minWidth:'85px'
        },
        className: 'text-align-left'
      },
      {
        title:'状态',
        key:'status',
        sortable:true,
        containerStyle:{
          minWidth:'50px'
        },
        className: 'text-align-left'
      }
    ];

    this.TopbarApi = defaultFetcher({
      timeUnit: 'daily',
      endTime: this.current
    });

    this.chartApi = defaultFetcher({
      timeUnit: 'hourly',
      endTime: this.current,
      dateType: 'today'
    });

    this.listApi = defaultFetcher({
      action: 'anrlisttable',
      statusCode: () => this.$state.stateCodeSelectedValue,
      limit: () => this.$state.listLimit,
      offset: () => this.$state.listOffset,
      name: () => this.$state.searchValue
    }, this.getTableDate);

    this.$state.chartformatter = function () {
      let begin = moment(this.x).format('HH:mm');
      let end = moment(this.x + moment.duration(1, 'hours').valueOf()).format('HH:mm');

      let template = '<span>从 ' + begin + ' 到 '+ end + ' 的一小时内</span><br/>';

      template += _.map(this.points, (item) => {
        return '<span style="color:' + item.series.color + '">' + item.series.name + '</span><span style="margin-right: 8px"></span> ANR 率 : ' + numeral(item.y).format('0[.]00%') + '<span style="margin-right: 8px"></span> 活跃用户数 : ' + item.point.customData.alive;
      }).join('<br />');

      return template;
    };
  }

  $toggle_date_other_display() {
    this.$state.chartDateListOpened = !this.$state.chartDateListOpened;
    this.emit();
  }

  getTableDate() {
    return _.find(this.$state.tableDateList, (item) => {
      return item.value === this.$state.tableDateListSelectedValue;
    }, this).tag;
  }

  $custom_date_check(payload) {

    let targetValue = payload.item.value;
    if (!this.checkDateStatus(targetValue)) {
      return;
    }

    this.$state.chartDateListOpened = false;
    this.$state.chartDateListSelectedValue = targetValue;

    if (targetValue && !this.$state.chartDataSource[targetValue.toString()]) {
      this.fetch_chart_data(targetValue).done(() => {
        this.emit();
      });
    } else {
      this.refillChart();
      this.emit();
    }
  }

  $predefined_date_check(payload) {
    let checked = this.$state.chartDateCheckStatus[payload.dayUnit] = !this.$state.chartDateCheckStatus[payload.dayUnit];

    if(!this.checkDateStatus()) {
      this.$state.chartDateCheckStatus[payload.dayUnit] = !checked;
      return;
    }

    if (checked) {
      this.fetch_chart_data(payload.dayUnit).done(() => {
        this.emit();
      });
    } else {
      this.refillChart();
      this.emit();
    }
  }

  checkDateStatus(value) {
    let state = _.some(this.$state.chartDateCheckStatus, (item) => item);
    if (!state) {
      value = undefined === value ? this.$state.chartDateListSelectedValue : value;
      state = value !== null;
    }
    return state;
  }

  fetch_chart_data(dateName) {
    this.$state.chart = { loading: true };
    this.emit();

    let deferred = $.Deferred();
    if(!this.$state.chartDataSource[dateName]) {
      this.chartApi.fetch((options) => {
        switch (dateName) {
          case 'today':
            options.data.endTime = moment().valueOf();
            break;
          case 'yesterday':
            options.data.endTime = moment().subtract(1, 'days').endOf('day').valueOf();
            break;
          default:
            if (typeof dateName === 'number') {
              options.data.endTime = moment().subtract(dateName, 'days').endOf('day').valueOf();
            }
            break;
        }
        return options;
      }).done((json, params) => {

        this.$state.chartDataSource[dateName.toString()] = {json, dateName};

        this.refillChart();

        deferred.resolve();
      }).fail((err, params) => {
        this.$state.chartDateCheckStatus[dateName.toString()] = null;
        this.$state.chartDataSource[dateName.toString()] = null;

        this.emit();
        deferred.reject(err);
      });
    } else {
      this.refillChart();
      deferred.resolve();
    }

    return deferred.promise();
  }

  refillChart() {

    for (let item in this.$state.chartDataSource) {
      if (isNaN(parseInt(item)) && !this.$state.chartDataSource[item]) {
        this.$state.chartDateCheckStatus[item] = false;
      } else if (!this.$state.chartDataSource[item]) {
        this.$state.chartDateListSelectedValue = null;
      }
    }

    let dateNames = [];
    let status = this.$state.chartDateCheckStatus;
    for (let item in status) {
      if (status[item]) {
        dateNames.push(item);
      }
    }

    let series = [];
    let dataSource = this.$state.chartDataSource;
    for (let i = 0; i < dateNames.length; i++) {
      series.push(dataSource[dateNames[i]]);
    }

    let customStatus = this.$state.chartDateListSelectedValue;
    if (customStatus && dataSource[customStatus.toString()]) {
      series.push(dataSource[customStatus.toString()]);
    }

    //////////////////////////////////
    let list = series.map((item) => {
      let {dateName, json} = item;

      let spanTime = 0;
      switch (dateName) {
        case 'yesterday':
          spanTime = moment.duration(1, 'days').valueOf();
          break;
        default:
          if (typeof dateName === 'number') {
            spanTime = moment.duration(dateName, 'days').valueOf();
          }
          break;
      }

      let data = json.map((inner) => {
        return {
          x: inner.startTime + spanTime,
          y: inner.alive === 0 ? 0 : (inner.affected / inner.alive),
          customData: {
            alive: inner.alive
          }
        };
      });

      let result = {
        id: moment().valueOf(),
        data: data
      };

      switch (dateName) {
        case 'today':
          result.name = '今天';
          break;
        case 'yesterday':
          result.name = '昨天';
          break;
        default:
          result.name = dateName + ' 天前';
          break;
      }

      return result;
    });
    //////////////////////////////////////////////////////////

    this.$state.chart = {
      data: {
        yAxis: {
          offset:-5,
          labels: {
            formatter: function() {
              return numeral(this.value).format('0[.]00%');
            }
          }
        },
        series: list
      }
    };

    this.emit();
  }

  $change_status_code(payload) {
    this.$state.stateCodeSelectedValue = payload.value;
    this.fetch_table_data();
  }

  $change_table_date(payload) {
    this.$state.tableDateListSelectedValue = payload.value;
    this.fetch_table_data();
  }

  $search_list(payload) {
    this.$state.searchValue = payload.value;
    this.fetch_table_data();
  }

  fetch_table_data() {
    this.listApi.fetch().done((json, params) => {
      this.$state.list = {
        data: json,
        hasMore: this.$state.listLimit === json.length
      };
      this.$state.list.showMore = () => {
        let deferred = $.Deferred();
        this.listApi
            .fetch()
            .fail(innerError => deferred.reject(innerError))
            .done(innerJson => {
              this.$state.listOffset += innerJson.length;
              deferred.resolve({
                data: innerJson,
                hasMore: this.$state.listLimit === innerJson.length
              });
            });

        return deferred.promise();
      };

      this.emit();
    }).fail((err) => {
      this.$state.list.error = err;

      this.emit();
    });
  }

  $toggle_hidden_table(payload) {
    this.$state.showHiddenTable = payload.value;
    this.emit();
  }

  closeOtherDateMenu(e) {
    if (this.$state.chartDateListOpened) {
      let el = e.target
        , container = this.viewInstance.refs.dateOtherRoot;

      if (!$.contains(container,el)) {
        this.$state.chartDateListOpened = false;
        this.emit();
      }
    }
  }

  $resize_grid_size(payload) {
    if (payload.current.width < 1000 && this.$state.gridColumns[1].containerStyle.minWidth !== '50px') {
      this.$state.gridColumns = _.map(this.$state.gridColumns, (item, index) => {
        if (index === 0) {
          delete item.containerStyle;
        } else if (index === 1 || index === 2 || index === 3) {
          item.containerStyle = {minWidth:'50px'};
        }
        return item;
      });
      this.emit();
    } else if (payload.current.width >= 1000 && this.$state.gridColumns[1].containerStyle.minWidth !== '75px') {
      this.$state.gridColumns = _.map(this.$state.gridColumns, (item, index) => {
        if (index === 0) {
          item.containerStyle = {width:'48%'};
        } else if (index === 1) {
          item.containerStyle = {minWidth:'75px'};
        } else if (index === 2) {
          item.containerStyle = {minWidth:'85px'};
        } else if (index === 3) {
          item.containerStyle = {minWidth:'90px'};
        }
        return item;
      });
      this.emit();
    }
  }

  $load() {
    $('body').on('click', this.closeOtherDateMenu);
    this.TopbarApi.fetch().done((json) => {
      let item = json[0];

      _.extend(this.$state, {
        anrRate: item.alive === 0 ? '--' : numeral(item.affected / item.alive).format('0[.]00%'),
        anrCount: item.count,
        anrUserCount: item.affected
      });

      this.emit();
    }).fail(() => {
      _.extend(this.$state, {
        anrRate: 'error',
        anrCount: 'error',
        anrUserCount: 'error'
      });
      this.emit();
    });

    this.fetch_chart_data('today').done(() => {
      this.emit();
    });

    this.fetch_table_data();
  }

  $unload() {
    $('body').off('click', this.closeOtherDateMenu);
  }
}
